library(dplyr)
library(readr)
library(tidyr)
library(stringr)
library(ggplot2)
library(wesanderson)
library(RColorBrewer)
library(flextable)
library(TwoSampleMR)
ao <- available_outcomes()
rm(dat)
object 'dat' not found
dat <- read_tsv("../query_results/bc_all_mr.tsv") %>%
mutate(outcome = case_when(
outcome.id %in% c('ieu-a-1127','ieu-a-1132', 'ieu-a-1133', 'ieu-a-1134') ~ 'ER+ postmeno',
outcome.id %in% c('ieu-a-1128','ieu-a-1135', 'ieu-a-1136', 'ieu-a-1137') ~ 'ER- premeno',
outcome.id %in% c('ieu-a-1126','ieu-a-1129', 'ieu-a-1130', 'ieu-a-1131') ~ 'Breast cancer (all)',
outcome.id %in% c('ukb-a-519','ukb-a-55') ~ 'ER+ postmeno UKB')) %>%
mutate(chip = case_when(
outcome.id %in% c('ieu-a-1126','ieu-a-1127', 'ieu-a-1128') ~ 'Meta',
outcome.id %in% c('ieu-a-1129', 'ieu-a-1132','ieu-a-1135') ~ 'OncArr',
outcome.id %in% c('ieu-a-1130', 'ieu-a-1133','ieu-a-1136') ~ 'iCOGS',
outcome.id %in% c('ieu-a-1131', 'ieu-a-1134','ieu-a-1137') ~ 'Old',
outcome.id %in% c('ukb-a-519','ukb-a-55') ~ 'UKBB')) %>%
mutate(outcome.details = paste0(outcome.id, " (",format(outcome.sample_size, big.mark = ","))) %>%
separate(outcome.details, into=c('outcome.details', 'tmp'), sep=",") %>%
mutate(outcome.details = gsub("ieu-a-|ukb-a-", '', outcome.details),
outcome.details = paste0(chip, ": ",outcome.details, "K)"))
dat<- dat %>%
mutate(outcome.details = factor(outcome.details, levels= c(
sort(unique(dat$outcome.details)[grepl('Meta', unique(dat$outcome.details))]),
sort(unique(dat$outcome.details)[grepl('OncArr', unique(dat$outcome.details))]),
sort(unique(dat$outcome.details)[grepl('iCOGS', unique(dat$outcome.details))]),
sort(unique(dat$outcome.details)[grepl('Old', unique(dat$outcome.details))]),
sort(unique(dat$outcome.details)[grepl('UKBB', unique(dat$outcome.details))]) ))) %>%
# convert MR results to OR
mutate(loci = mr.b - 1.96 * mr.se,
upci = mr.b + 1.96 * mr.se,
or = exp(mr.b),
or_loci = exp(loci),
or_upci = exp(upci),
OR_CI = paste0(round(or,2), " [",round(or_loci,2) ,":",round(or_upci,2), "]")) %>%
mutate(effect_direction = ifelse(or_loci > 1 & or_upci > 1, 'positive',
ifelse(or_loci < 1 & or_upci < 1, 'negative', 'overlaps null'))) %>%
mutate(mr.b = round(mr.b, 3)) %>%
# subset
filter(exposure.sex != 'Males') %>%
filter(chip!='old') %>%
#filter(mr.pval < 10e-6) %>%
# create categories of exposure traits
# tidy up labels
mutate(exposure = str_replace(exposure.trait, "Treatment/medication code", "Drug"),
exposure = str_replace(exposure, "Non-cancer illness code self-reported", "Illness"),
exposure = str_replace(exposure, "Diagnoses - main ICD10:", "Diagnosis"),
exposure = str_replace(exposure, "Mineral and other dietary supplements:", "Supplements"),
exposure = str_replace(exposure, "Vitamin and mineral supplements:", "Vitamins"),
exposure = str_replace(exposure, "Illness injury bereavement stress in last 2 years", "Stress"),
exposure = str_replace(exposure, "Types of transport used (excluding work)", "Transport"),
exposure = str_replace(exposure, "Types of physical activity in last 4 weeks", "Physical activity")) %>%
mutate(exposure = case_when(grepl("presbyopia", exposure) ~ "Eyesight problems1",
grepl("hypermetropia", exposure) ~ "Eyesight problems2",
TRUE ~ exposure)) %>%
mutate(exposure_cat = case_when(
grepl("Drug", exposure) ~ "drugs",
grepl("Diagnos|Illness|cancer|diagnos|death|disorder|eye|carcino|colitis|disease", exposure, ignore.case = T) ~ "disease",
grepl("vitamin|suppl", exposure, ignore.case = T) ~ "vitamin",
grepl("waist|hip|obesity|trunk|mass|weight|bmi|body size|height|length|impedance", exposure, ignore.case = T) ~ "antrophometric",
grepl("age at|age started", exposure, ignore.case = T) ~ "reproductive",
grepl("alco|wine", exposure, ignore.case = T) ~ "alcohol",
grepl("smok|cigar", exposure, ignore.case = T) ~ "smoking",
grepl("activi|transport|diy", exposure, ignore.case = T) ~ "activity",
TRUE ~ 'other'))
# add notes for trats
exposure_notes <- ao %>% filter(id %in% dat$exposure.id) %>% select(id, note)
dat<- dat %>%
left_join(exposure_notes, by = c('exposure.id'='id')) %>%
# add other exposure details
mutate(exposure = case_when(
exposure.sex == 'Females' ~ paste0(exposure, " (F) ", coalesce(consortium, author),"/" , year),
TRUE ~ paste0(exposure, " (M/F) ", coalesce(consortium, author),"/" , year))) %>%
# add note
mutate(exposure = case_when(grepl('Adjusted for BMI', note) ~ paste0(exposure, " AdjBMI"),
TRUE ~ exposure))
outcome_table<- dat %>%
select(outcome, outcome.id, outcome.sample_size, N_case, chip)%>%
distinct() %>%
arrange(outcome, desc(outcome.sample_size)) %>%
rename(`sample_size`=outcome.sample_size)
set_flextable_defaults(big.mark = " ",
font.size = 10, theme_fun = theme_vanilla,
padding.bottom = 6,
padding.top = 6,
padding.left = 6,
padding.right = 6,
background.color = "#EFEFEF")
ft<-flextable(outcome_table)
ft<-width(ft, j = 1, width=1.5)
ft
outcome | outcome.id | sample_size | N_case | chip |
Breast cancer (all) | ieu-a-1126 | 228 951 | 122 977 | Meta |
Breast cancer (all) | ieu-a-1129 | 106 776 | 61 282 | OncArr |
Breast cancer (all) | ieu-a-1130 | 89 677 | 46 785 | iCOGS |
Breast cancer (all) | ieu-a-1131 | 32 498 | 14 910 | Old |
ER- premeno | ieu-a-1128 | 127 442 | 21 468 | Meta |
ER- premeno | ieu-a-1135 | 55 149 | 9 655 | OncArr |
ER- premeno | ieu-a-1136 | 50 225 | 7 333 | iCOGS |
ER- premeno | ieu-a-1137 | 22 068 | 4 480 | Old |
ER+ postmeno | ieu-a-1127 | 175 475 | 69 501 | Meta |
ER+ postmeno | ieu-a-1132 | 83 691 | 38 197 | OncArr |
ER+ postmeno | ieu-a-1133 | 69 970 | 27 078 | iCOGS |
ER+ postmeno | ieu-a-1134 | 21 814 | 4 226 | Old |
ER+ postmeno UKB | ukb-a-519 | 337 199 | 5 510 | UKBB |
ER+ postmeno UKB | ukb-a-55 | 337 159 | 7 480 | UKBB |
NA
NA
Anthophometric traits
input <- dat %>% filter(exposure_cat %in% c('antrophometric')) %>%
mutate(exposure = gsub("Comparative ", "", exposure))
p<-plot_heatmap(input)
p
input <- dat %>% filter(exposure_cat %in% c('antrophometric')) %>%
mutate(exposure = gsub("Comparative ", "", exposure))
p<-plot_bubble_plot(input)
p

Activity
input <- dat %>% filter(exposure_cat %in% c('activity')) %>%
mutate(exposure = gsub("\\(eg.*)", "", exposure))
p<-plot_heatmap(input)
p
input <- dat %>% filter(exposure_cat %in% c('activity')) %>%
mutate(exposure = gsub("\\(eg.*)", "", exposure))
p<-plot_bubble_plot(input)
p

Supplements / vitamins
input <- dat %>% filter(exposure_cat %in% c('vitamin'))
p<-plot_heatmap(input)
p
input <- dat %>% filter(exposure_cat %in% c('vitamin'))
p<-plot_bubble_plot(input)
p

Reproductive traits
input <- dat %>% filter(exposure_cat %in% c('reproductive')) %>%
mutate(exposure = gsub("\\(eg.*)", "", exposure))
p<-plot_heatmap(input)
p
input <- dat %>% filter(exposure_cat %in% c('reproductive')) %>%
mutate(exposure = gsub("\\(eg.*)", "", exposure))
p<-plot_bubble_plot(input)
p

ply<-plotly::ggplotly(p)
ply
Other
input <- dat %>% filter(exposure_cat %in% c('other')) %>%
filter(!grepl("inhaler", exposure))
p<-plot_heatmap(input)
p
input <- dat %>% filter(exposure_cat %in% c('other')) %>%
filter(!grepl("inhaler", exposure))
p<-plot_bubble_plot(input)
p

Drugs
input <- dat %>% filter(exposure_cat %in% c('drugs'))
p<-plot_bubble_plot(input)
p

Disease
input <- dat %>% filter(exposure_cat %in% c('disease'))
p<-plot_bubble_plot(input)
p

ply<-plotly::ggplotly(p)
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
ply
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgbWVzc2FnZT1GfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoZmxleHRhYmxlKQpsaWJyYXJ5KFR3b1NhbXBsZU1SKQoKaWYgKCFleGlzdHMoImFvIikpIHsKICBhbyA8LSBhdmFpbGFibGVfb3V0Y29tZXMoKQp9CmBgYAoKCmBgYHtyLCBtZXNzYWdlID0gRkFMU0V9CnJtKGRhdCkKZGF0IDwtIHJlYWRfdHN2KCIuLi9xdWVyeV9yZXN1bHRzL2JjX2FsbF9tci50c3YiKSAlPiUgCiAgbXV0YXRlKG91dGNvbWUgPSBjYXNlX3doZW4oCiAgICAgICAgb3V0Y29tZS5pZCAlaW4lIGMoJ2lldS1hLTExMjcnLCdpZXUtYS0xMTMyJywgJ2lldS1hLTExMzMnLCAnaWV1LWEtMTEzNCcpIH4gJ0VSKyBwb3N0bWVubycsCiAgICAgICAgb3V0Y29tZS5pZCAlaW4lIGMoJ2lldS1hLTExMjgnLCdpZXUtYS0xMTM1JywgJ2lldS1hLTExMzYnLCAnaWV1LWEtMTEzNycpIH4gJ0VSLSBwcmVtZW5vJywKICAgICAgICBvdXRjb21lLmlkICVpbiUgYygnaWV1LWEtMTEyNicsJ2lldS1hLTExMjknLCAnaWV1LWEtMTEzMCcsICdpZXUtYS0xMTMxJykgfiAnQnJlYXN0IGNhbmNlciAoYWxsKScsCiAgICAgICAgb3V0Y29tZS5pZCAlaW4lIGMoJ3VrYi1hLTUxOScsJ3VrYi1hLTU1JykgfiAnRVIrIHBvc3RtZW5vIFVLQicpKSAlPiUgCiAgbXV0YXRlKGNoaXAgPSBjYXNlX3doZW4oCiAgICAgICAgb3V0Y29tZS5pZCAlaW4lIGMoJ2lldS1hLTExMjYnLCdpZXUtYS0xMTI3JywgJ2lldS1hLTExMjgnKSB+ICdNZXRhJywKICAgICAgICBvdXRjb21lLmlkICVpbiUgYygnaWV1LWEtMTEyOScsICdpZXUtYS0xMTMyJywnaWV1LWEtMTEzNScpIH4gJ09uY0FycicsCiAgICAgICAgb3V0Y29tZS5pZCAlaW4lIGMoJ2lldS1hLTExMzAnLCAnaWV1LWEtMTEzMycsJ2lldS1hLTExMzYnKSB+ICdpQ09HUycsCiAgICAgICAgb3V0Y29tZS5pZCAlaW4lIGMoJ2lldS1hLTExMzEnLCAnaWV1LWEtMTEzNCcsJ2lldS1hLTExMzcnKSB+ICdPbGQnLAogICAgICAgIG91dGNvbWUuaWQgJWluJSBjKCd1a2ItYS01MTknLCd1a2ItYS01NScpIH4gICAgICAgICAgICAgICAgICAnVUtCQicpKSAlPiUgCiAgbXV0YXRlKG91dGNvbWUuZGV0YWlscyA9ICBwYXN0ZTAob3V0Y29tZS5pZCwgIiAoIixmb3JtYXQob3V0Y29tZS5zYW1wbGVfc2l6ZSwgYmlnLm1hcmsgPSAiLCIpKSkgJT4lIAogIHNlcGFyYXRlKG91dGNvbWUuZGV0YWlscywgaW50bz1jKCdvdXRjb21lLmRldGFpbHMnLCAndG1wJyksIHNlcD0iLCIpICU+JSAKICBtdXRhdGUob3V0Y29tZS5kZXRhaWxzID0gZ3N1YigiaWV1LWEtfHVrYi1hLSIsICcnLCBvdXRjb21lLmRldGFpbHMpLAogICAgICAgICBvdXRjb21lLmRldGFpbHMgPSBwYXN0ZTAoY2hpcCwgIjogIixvdXRjb21lLmRldGFpbHMsICJLKSIpKQoKZGF0PC0gZGF0ICU+JSAKICBtdXRhdGUob3V0Y29tZS5kZXRhaWxzID0gZmFjdG9yKG91dGNvbWUuZGV0YWlscywgbGV2ZWxzPSBjKCAKICAgICAgICAgICAgICAgICAgICBzb3J0KHVuaXF1ZShkYXQkb3V0Y29tZS5kZXRhaWxzKVtncmVwbCgnTWV0YScsIHVuaXF1ZShkYXQkb3V0Y29tZS5kZXRhaWxzKSldKSwKICAgICAgICAgICAgICAgICAgICBzb3J0KHVuaXF1ZShkYXQkb3V0Y29tZS5kZXRhaWxzKVtncmVwbCgnT25jQXJyJywgdW5pcXVlKGRhdCRvdXRjb21lLmRldGFpbHMpKV0pLAogICAgICAgICAgICAgICAgICAgIHNvcnQodW5pcXVlKGRhdCRvdXRjb21lLmRldGFpbHMpW2dyZXBsKCdpQ09HUycsIHVuaXF1ZShkYXQkb3V0Y29tZS5kZXRhaWxzKSldKSwKICAgICAgICAgICAgICAgICAgICBzb3J0KHVuaXF1ZShkYXQkb3V0Y29tZS5kZXRhaWxzKVtncmVwbCgnT2xkJywgdW5pcXVlKGRhdCRvdXRjb21lLmRldGFpbHMpKV0pLAogICAgICAgICAgICAgICAgICAgIHNvcnQodW5pcXVlKGRhdCRvdXRjb21lLmRldGFpbHMpW2dyZXBsKCdVS0JCJywgdW5pcXVlKGRhdCRvdXRjb21lLmRldGFpbHMpKV0pICApKSkgJT4lIAogICMgY29udmVydCBNUiByZXN1bHRzIHRvIE9SCiAgbXV0YXRlKGxvY2kgPSBtci5iIC0gMS45NiAqIG1yLnNlLCAKICAgICAgICAgdXBjaSA9IG1yLmIgKyAxLjk2ICogbXIuc2UsCiAgICAgICAgIG9yID0gZXhwKG1yLmIpLCAKICAgICAgICAgb3JfbG9jaSA9IGV4cChsb2NpKSwgCiAgICAgICAgIG9yX3VwY2kgPSBleHAodXBjaSksCiAgICAgICAgIE9SX0NJID0gcGFzdGUwKHJvdW5kKG9yLDIpLCAiIFsiLHJvdW5kKG9yX2xvY2ksMikgLCI6Iixyb3VuZChvcl91cGNpLDIpLCAiXSIpKSAlPiUgCiAgbXV0YXRlKGVmZmVjdF9kaXJlY3Rpb24gPSBpZmVsc2Uob3JfbG9jaSA+IDEgJiBvcl91cGNpID4gMSwgJ3Bvc2l0aXZlJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShvcl9sb2NpIDwgMSAmIG9yX3VwY2kgPCAxLCAnbmVnYXRpdmUnLCAnb3ZlcmxhcHMgbnVsbCcpKSkgJT4lIAogIG11dGF0ZShtci5iID0gcm91bmQobXIuYiwgMykpICU+JSAKICAjIHN1YnNldCAKICBmaWx0ZXIoZXhwb3N1cmUuc2V4ICE9ICdNYWxlcycpICU+JSAKICBmaWx0ZXIoY2hpcCE9J29sZCcpICU+JSAKICAjZmlsdGVyKG1yLnB2YWwgPCAxMGUtNikgJT4lIAogICMgY3JlYXRlIGNhdGVnb3JpZXMgb2YgZXhwb3N1cmUgdHJhaXRzCiAgICAgICMgdGlkeSB1cCBsYWJlbHMKICAgbXV0YXRlKGV4cG9zdXJlID0gc3RyX3JlcGxhY2UoZXhwb3N1cmUudHJhaXQsICJUcmVhdG1lbnQvbWVkaWNhdGlvbiBjb2RlIiwgIkRydWciKSwKICAgICAgICAgIGV4cG9zdXJlID0gc3RyX3JlcGxhY2UoZXhwb3N1cmUsICJOb24tY2FuY2VyIGlsbG5lc3MgY29kZSAgc2VsZi1yZXBvcnRlZCIsICJJbGxuZXNzIiksCiAgICAgICAgICBleHBvc3VyZSA9IHN0cl9yZXBsYWNlKGV4cG9zdXJlLCAiRGlhZ25vc2VzIC0gbWFpbiBJQ0QxMDoiLCAiRGlhZ25vc2lzIiksCiAgICAgICAgICBleHBvc3VyZSA9IHN0cl9yZXBsYWNlKGV4cG9zdXJlLCAiTWluZXJhbCBhbmQgb3RoZXIgZGlldGFyeSBzdXBwbGVtZW50czoiLCAiU3VwcGxlbWVudHMiKSwKICAgICAgICAgIGV4cG9zdXJlID0gc3RyX3JlcGxhY2UoZXhwb3N1cmUsICJWaXRhbWluIGFuZCBtaW5lcmFsIHN1cHBsZW1lbnRzOiIsICJWaXRhbWlucyIpLAogICAgICAgICAgZXhwb3N1cmUgPSBzdHJfcmVwbGFjZShleHBvc3VyZSwgIklsbG5lc3MgIGluanVyeSAgYmVyZWF2ZW1lbnQgIHN0cmVzcyBpbiBsYXN0IDIgeWVhcnMiLCAiU3RyZXNzIiksCiAgICAgICAgICBleHBvc3VyZSA9IHN0cl9yZXBsYWNlKGV4cG9zdXJlLCAiVHlwZXMgb2YgdHJhbnNwb3J0IHVzZWQgKGV4Y2x1ZGluZyB3b3JrKSIsICJUcmFuc3BvcnQiKSwKICAgICAgICAgIGV4cG9zdXJlID0gc3RyX3JlcGxhY2UoZXhwb3N1cmUsICJUeXBlcyBvZiBwaHlzaWNhbCBhY3Rpdml0eSBpbiBsYXN0IDQgd2Vla3MiLCAiUGh5c2ljYWwgYWN0aXZpdHkiKSkgJT4lIAogIG11dGF0ZShleHBvc3VyZSA9IGNhc2Vfd2hlbihncmVwbCgicHJlc2J5b3BpYSIsIGV4cG9zdXJlKSB+ICJFeWVzaWdodCBwcm9ibGVtczEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiaHlwZXJtZXRyb3BpYSIsIGV4cG9zdXJlKSB+ICJFeWVzaWdodCBwcm9ibGVtczIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gZXhwb3N1cmUpKSAlPiUgCiAgbXV0YXRlKGV4cG9zdXJlX2NhdCA9IGNhc2Vfd2hlbigKICAgICAgICAgIGdyZXBsKCJEcnVnIiwgZXhwb3N1cmUpIH4gImRydWdzIiwKICAgICAgICAgIGdyZXBsKCJEaWFnbm9zfElsbG5lc3N8Y2FuY2VyfGRpYWdub3N8ZGVhdGh8ZGlzb3JkZXJ8ZXllfGNhcmNpbm98Y29saXRpc3xkaXNlYXNlIiwgZXhwb3N1cmUsIGlnbm9yZS5jYXNlID0gVCkgfiAiZGlzZWFzZSIsCiAgICAgICAgICBncmVwbCgidml0YW1pbnxzdXBwbCIsIGV4cG9zdXJlLCBpZ25vcmUuY2FzZSA9IFQpIH4gInZpdGFtaW4iLAogICAgICAgICAgZ3JlcGwoIndhaXN0fGhpcHxvYmVzaXR5fHRydW5rfG1hc3N8d2VpZ2h0fGJtaXxib2R5IHNpemV8aGVpZ2h0fGxlbmd0aHxpbXBlZGFuY2UiLCBleHBvc3VyZSwgaWdub3JlLmNhc2UgPSBUKSB+ICJhbnRyb3Bob21ldHJpYyIsCiAgICAgICAgICBncmVwbCgiYWdlIGF0fGFnZSBzdGFydGVkIiwgZXhwb3N1cmUsIGlnbm9yZS5jYXNlID0gVCkgfiAicmVwcm9kdWN0aXZlIiwKICAgICAgICAgIGdyZXBsKCJhbGNvfHdpbmUiLCBleHBvc3VyZSwgaWdub3JlLmNhc2UgPSBUKSB+ICJhbGNvaG9sIiwKICAgICAgICAgIGdyZXBsKCJzbW9rfGNpZ2FyIiwgZXhwb3N1cmUsIGlnbm9yZS5jYXNlID0gVCkgfiAic21va2luZyIsCiAgICAgICAgICBncmVwbCgiYWN0aXZpfHRyYW5zcG9ydHxkaXkiLCBleHBvc3VyZSwgaWdub3JlLmNhc2UgPSBUKSB+ICJhY3Rpdml0eSIsCiAgICAgICAgICBUUlVFIH4gJ290aGVyJykpIAogIAojIGFkZCBub3RlcyBmb3IgdHJhdHMKZXhwb3N1cmVfbm90ZXMgPC0gYW8gJT4lIGZpbHRlcihpZCAlaW4lIGRhdCRleHBvc3VyZS5pZCkgJT4lIHNlbGVjdChpZCwgbm90ZSkKCmRhdDwtIGRhdCAlPiUgCiAgbGVmdF9qb2luKGV4cG9zdXJlX25vdGVzLCBieSA9IGMoJ2V4cG9zdXJlLmlkJz0naWQnKSkgJT4lIAogICMgYWRkIG90aGVyIGV4cG9zdXJlIGRldGFpbHMKICBtdXRhdGUoZXhwb3N1cmUgPSBjYXNlX3doZW4oCiAgICBleHBvc3VyZS5zZXggPT0gJ0ZlbWFsZXMnIH4gcGFzdGUwKGV4cG9zdXJlLCAiIChGKSAiLCBjb2FsZXNjZShjb25zb3J0aXVtLCBhdXRob3IpLCIvIiAsIHllYXIpLAogICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IHBhc3RlMChleHBvc3VyZSwgIiAoTS9GKSAiLCBjb2FsZXNjZShjb25zb3J0aXVtLCBhdXRob3IpLCIvIiAsIHllYXIpKSkgJT4lIAogICMgYWRkIG5vdGUKICBtdXRhdGUoZXhwb3N1cmUgPSBjYXNlX3doZW4oZ3JlcGwoJ0FkanVzdGVkIGZvciBCTUknLCBub3RlKSB+IHBhc3RlMChleHBvc3VyZSwgIiBBZGpCTUkiKSwKICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IGV4cG9zdXJlKSkgCgpgYGAKCmBgYHtyfQpvdXRjb21lX3RhYmxlPC0gZGF0ICU+JSAKICBzZWxlY3Qob3V0Y29tZSwgb3V0Y29tZS5pZCwgb3V0Y29tZS5zYW1wbGVfc2l6ZSwgTl9jYXNlLCBjaGlwKSU+JSAKICBkaXN0aW5jdCgpICU+JQogIGFycmFuZ2Uob3V0Y29tZSwgZGVzYyhvdXRjb21lLnNhbXBsZV9zaXplKSkgJT4lIAogIHJlbmFtZShgc2FtcGxlX3NpemVgPW91dGNvbWUuc2FtcGxlX3NpemUpCgoKc2V0X2ZsZXh0YWJsZV9kZWZhdWx0cyhiaWcubWFyayA9ICIgIiwgCiAgZm9udC5zaXplID0gMTAsIHRoZW1lX2Z1biA9IHRoZW1lX3ZhbmlsbGEsCiAgcGFkZGluZy5ib3R0b20gPSA2LCAKICBwYWRkaW5nLnRvcCA9IDYsCiAgcGFkZGluZy5sZWZ0ID0gNiwKICBwYWRkaW5nLnJpZ2h0ID0gNiwKICBiYWNrZ3JvdW5kLmNvbG9yID0gIiNFRkVGRUYiKQoKZnQ8LWZsZXh0YWJsZShvdXRjb21lX3RhYmxlKQpmdDwtd2lkdGgoZnQsIGogPSAxLCB3aWR0aD0xLjUpCmZ0CgoKYGBgCgoKCmBgYHtyIGluY2x1ZGU9Rn0KIyBoZWF0bWFwIGZ1bmN0aW9uCnBsb3RfaGVhdG1hcCA8LSBmdW5jdGlvbihpbnB1dCl7CiAgCiAgI3BhbCA8LSB3ZXNfcGFsZXR0ZSgiWmlzc291MSIsIDEwMCwgdHlwZSA9ICJjb250aW51b3VzIikKICBsaW1pdCA8LSBtYXgoYWJzKGlucHV0JG1yLmIpKSAqIGMoLTEsIDEpCiAgCiAgY29sb3VyQ291bnQgPSBsZW5ndGgodW5pcXVlKGlucHV0JG1yLmIpKQogIGdldFBhbGV0dGU8LWNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwobj03LCBuYW1lID0gIlBpWUciKSkpCgogIHA8LWdncGxvdChpbnB1dCwgYWVzKCBvdXRjb21lLmRldGFpbHMsIGV4cG9zdXJlLnRyYWl0LCBmaWxsPSBtci5iLCBsYWJlbCA9IG1yLnB2YWwsIGxhYmVsMiA9IE9SX0NJLCBsYWJlbDMgPSBleHBvc3VyZS5zZXgpKSArIAogICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IGdldFBhbGV0dGUoMTEpLCBsaW1pdHM9bGltaXQpICsgCiAgICBnZW9tX3RpbGUoKSsKICAgIHNjYWxlX3lfZGlzY3JldGUocG9zaXRpb24gPSAicmlnaHQiKSsKICAgIGZhY2V0X2dyaWQoZXhwb3N1cmVfY2F0fm91dGNvbWUsIHNjYWxlcyA9ICdmcmVlJykgKwogICAgdGhlbWVfYncoKSsKICAgIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT0zNSwgaGp1c3Q9MSksIGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykKICByZXR1cm4ocCkKfQoKcGxvdF9idWJibGVfcGxvdCA8LSBmdW5jdGlvbihpbnB1dCl7CiAgCiAgIyBmaXJzdCwgY3JlYXRlIGEgdXNhYmxlIHAtdmFsdWUgdmFyaWFibGUgKHRydW5jYXRlZCBhbmQgbG9nMTAtdHJhbnNmb3JtZWQpCiAgaW5wdXQgPC0gbXV0YXRlKGlucHV0LCAKICAgICAgICAgICAgIyBjb252ZXJ0IGFsbCBzdXBlciBzbWFsbCBwdmFsIGludG8gMWUtMTUKICAgICAgICAgICAgcHZhbF90cnVuY2F0ZWQgPSBpZmVsc2UobXIucHZhbCA8IDFlLTE1LCAxZS0xNSwgbXIucHZhbCksCiAgICAgICAgICAgICMgbG9nIHRyYW5zZm9ybSBwdmFscwogICAgICAgICAgICBsb2cxMHB2YWxfdHJ1bmMgPSBhcy5pbnRlZ2VyKC1sb2cxMChwdmFsX3RydW5jYXRlZCkpKQogIAogIAogICNwYWwgPC0gd2VzX3BhbGV0dGUoIlppc3NvdTEiLCAxMDAsIHR5cGUgPSAiY29udGludW91cyIpCiAgbGltaXQgPC0gbWF4KGFicyhpbnB1dCRtci5iKSkgKiBjKC0xLCAxKQogIAogIGNvbG91ckNvdW50ID0gbGVuZ3RoKHVuaXF1ZShpbnB1dCRtci5iKSkKICBnZXRQYWxldHRlPC1jb2xvclJhbXBQYWxldHRlKHJldihicmV3ZXIucGFsKG49NywgbmFtZSA9ICJQaVlHIikpKQogIAogIHA8LWdncGxvdChpbnB1dCwgYWVzKCBvdXRjb21lLmRldGFpbHMsIHJlb3JkZXIoZXhwb3N1cmUsIG1yLmIpLCAKICAgICAgICAgICAgICAgICAgY29sb3I9IGZhY3Rvcihtci5iKSwgc2l6ZSA9IGxvZzEwcHZhbF90cnVuYywgbGFiZWwyID0gT1JfQ0ksIGxhYmVsMyA9IGV4cG9zdXJlLnNleCkpICsgCiAgICBnZW9tX3BvaW50KCkrCiAgICBzY2FsZV9zaXplKGJyZWFrcyA9IGMoMCw1LDcsMTUpKSsKICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gZ2V0UGFsZXR0ZShjb2xvdXJDb3VudCkpKyAjIHVuZmFpciBzY2FsZSArIG5lZWQgZmFjdG9yICYgbm8gbGVnZW5kCiAgICAjc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzID0gZ2V0UGFsZXR0ZSgxMSksIGxpbWl0cz1saW1pdCkrICNmYWlyIHNjYWxlCiAgICAKICAgIHNjYWxlX3lfZGlzY3JldGUocG9zaXRpb24gPSAicmlnaHQiKSsKICAgIGZhY2V0X2dyaWQoZXhwb3N1cmVfY2F0fm91dGNvbWUsIHNjYWxlcyA9ICdmcmVlJykgKwogICAgdGhlbWVfbGlnaHQoKSsKICAgICN0aGVtZV9zb2xhcml6ZWQoKSsKICAgIGxhYnMoc2l6ZT0iLWxvZzEwKHB2YWwpIiwgY29sb3I9J2JldGEnLCB5PSIiLCB4PSIiKSsKICAgIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT0zNSwgaGp1c3Q9MSksIGxlZ2VuZC5wb3NpdGlvbiA9ICdsZWZ0JykrCiAgICAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpCiAgcmV0dXJuKHApCn0KCgpgYGAKCgoKIyMjIEFudGhvcGhvbWV0cmljIHRyYWl0cwpgYGB7ciBmaWcud2lkdGg9OH0KaW5wdXQgPC0gZGF0ICU+JSBmaWx0ZXIoZXhwb3N1cmVfY2F0ICVpbiUgYygnYW50cm9waG9tZXRyaWMnKSkgJT4lIAogICBtdXRhdGUoZXhwb3N1cmUgPSBnc3ViKCJDb21wYXJhdGl2ZSAiLCAiIiwgZXhwb3N1cmUpKSAKCnA8LXBsb3RfaGVhdG1hcChpbnB1dCkKcApgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTB9CmlucHV0IDwtIGRhdCAlPiUgZmlsdGVyKGV4cG9zdXJlX2NhdCAlaW4lIGMoJ2FudHJvcGhvbWV0cmljJykpICU+JSAKICAgbXV0YXRlKGV4cG9zdXJlID0gZ3N1YigiQ29tcGFyYXRpdmUgIiwgIiIsIGV4cG9zdXJlKSkgCnA8LXBsb3RfYnViYmxlX3Bsb3QoaW5wdXQpCnAKYGBgCgojIyMgQWN0aXZpdHkKCmBgYHtyIGZpZy53aWR0aD0xMCwgZXZhbD1GfQppbnB1dCA8LSBkYXQgJT4lIGZpbHRlcihleHBvc3VyZV9jYXQgJWluJSBjKCdhY3Rpdml0eScpKSAlPiUgCiAgICAgICAgICAgICAgICBtdXRhdGUoZXhwb3N1cmUgPSBnc3ViKCJcXChlZy4qKSIsICIiLCBleHBvc3VyZSkpCnA8LXBsb3RfaGVhdG1hcChpbnB1dCkKcApgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KaW5wdXQgPC0gZGF0ICU+JSBmaWx0ZXIoZXhwb3N1cmVfY2F0ICVpbiUgYygnYWN0aXZpdHknKSkgJT4lIAogICAgICAgICAgICAgIG11dGF0ZShleHBvc3VyZSA9IGdzdWIoIlxcKGVnLiopIiwgIiIsIGV4cG9zdXJlKSkKcDwtcGxvdF9idWJibGVfcGxvdChpbnB1dCkKcApgYGAKCiMjIyBTdXBwbGVtZW50cyAvIHZpdGFtaW5zCgpgYGB7ciBmaWcud2lkdGg9MTAsIGV2YWw9Rn0KaW5wdXQgPC0gZGF0ICU+JSBmaWx0ZXIoZXhwb3N1cmVfY2F0ICVpbiUgYygndml0YW1pbicpKSAKcDwtcGxvdF9oZWF0bWFwKGlucHV0KQpwCmBgYAoKYGBge3IgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTV9CmlucHV0IDwtIGRhdCAlPiUgZmlsdGVyKGV4cG9zdXJlX2NhdCAlaW4lIGMoJ3ZpdGFtaW4nKSkgCnA8LXBsb3RfYnViYmxlX3Bsb3QoaW5wdXQpCnAKYGBgCgoKIyMjIFJlcHJvZHVjdGl2ZSB0cmFpdHMKYGBge3IgZmlnLmhlaWdodD01LCBldmFsPUZ9CmlucHV0IDwtIGRhdCAlPiUgZmlsdGVyKGV4cG9zdXJlX2NhdCAlaW4lIGMoJ3JlcHJvZHVjdGl2ZScpKSAlPiUgCiAgICAgICAgICAgICAgICBtdXRhdGUoZXhwb3N1cmUgPSBnc3ViKCJcXChlZy4qKSIsICIiLCBleHBvc3VyZSkpCnA8LXBsb3RfaGVhdG1hcChpbnB1dCkKcApgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9M30KaW5wdXQgPC0gZGF0ICU+JSBmaWx0ZXIoZXhwb3N1cmVfY2F0ICVpbiUgIGMoJ3JlcHJvZHVjdGl2ZScpKSAlPiUgCiAgICAgICAgICAgICAgICBtdXRhdGUoZXhwb3N1cmUgPSBnc3ViKCJcXChlZy4qKSIsICIiLCBleHBvc3VyZSkpCnA8LXBsb3RfYnViYmxlX3Bsb3QoaW5wdXQpCnAKYGBgCgo8YnI+CgpgYGB7ciwgZXZhbD1GfQpwbHk8LXBsb3RseTo6Z2dwbG90bHkocCkKcGx5CmBgYAoKCiMjIyBPdGhlcgpgYGB7ciBmaWcud2lkdGg9MTIsIGV2YWw9Rn0KaW5wdXQgPC0gZGF0ICU+JSBmaWx0ZXIoZXhwb3N1cmVfY2F0ICVpbiUgYygnb3RoZXInKSkgJT4lIAogICAgICAgICAgICAgICAgZmlsdGVyKCFncmVwbCgiaW5oYWxlciIsIGV4cG9zdXJlKSkKcDwtcGxvdF9oZWF0bWFwKGlucHV0KQpwCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0xNX0KaW5wdXQgPC0gZGF0ICU+JSBmaWx0ZXIoZXhwb3N1cmVfY2F0ICVpbiUgYygnb3RoZXInKSkgJT4lIAogICAgICAgICAgICAgICAgZmlsdGVyKCFncmVwbCgiaW5oYWxlciIsIGV4cG9zdXJlKSkKcDwtcGxvdF9idWJibGVfcGxvdChpbnB1dCkKcApgYGAKCgoKCiMjIyBEcnVncwpgYGB7ciBmaWcud2lkdGg9MTJ9CmlucHV0IDwtIGRhdCAlPiUgZmlsdGVyKGV4cG9zdXJlX2NhdCAlaW4lIGMoJ2RydWdzJykpIApwPC1wbG90X2J1YmJsZV9wbG90KGlucHV0KQpwCmBgYAoKIyMjIERpc2Vhc2UKYGBge3IgZmlnLndpZHRoPTE1fQppbnB1dCA8LSBkYXQgJT4lIGZpbHRlcihleHBvc3VyZV9jYXQgJWluJSBjKCdkaXNlYXNlJykpIApwPC1wbG90X2J1YmJsZV9wbG90KGlucHV0KQpwCmBgYAoKYGBge3IgfQpwbHk8LXBsb3RseTo6Z2dwbG90bHkocCkKcGx5CmBgYAoK